package com.kinyx.framework.bean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.kinyx.framework.annotation.assist.CanNotNull;
import com.kinyx.framework.annotation.assist.CanNull;
import com.kinyx.framework.annotation.assist.ReturnNotNull;
import com.kinyx.framework.annotation.assist.ReturnNull;
import com.kinyx.framework.reflect.KTypeConverter;
import com.kinyx.framework.utils.KArrayUtils;
import com.kinyx.framework.utils.KListUtils;
import com.kinyx.framework.utils.KMatcherUtils;

/**
 * 主参数处理器
 */
public class MainArgs {

	Map<String, String> map = new HashMap<>();

	private MainArgs() {}
	private MainArgs(final String[] args) {
		if (KArrayUtils.isEmpty(args)) { return; }
		for (final String arg : args) {
			final int idx = arg.indexOf("=");
			if (idx == -1) { continue; }
			this.map.put(arg.substring(0, idx), arg.substring(idx + 1));
		}
	}

	/**
	 * 构造方法
	 * @return 新对象
	 */
	@ReturnNotNull
	public static MainArgs of() { return new MainArgs(); }

	/**
	 * 构造方法
	 * @param args 参数
	 * @return 新对象
	 */
	@ReturnNotNull
	public static MainArgs of(@CanNull final String[] args) { return new MainArgs(args); }

	/**
	 * 设置值
	 * @param key 键
	 * @param value 值
	 * @return 本对象
	 */
	@ReturnNotNull
	public MainArgs put(@CanNull final String key, @CanNull final String value) {
		this.map.put(key, value);
		return this;
	}

	/**
	 * 取值
	 * @param <T> 泛型
	 * @param type 类型
	 * @param key 键
	 * @return 值
	 */
	@ReturnNull("未配置该参数")
	@ReturnNull("配置的值为null")
	public <T> T get(@CanNotNull final Class<T> type, @CanNull final String key) {
		final String value = this.map.get(key);
		return value == null ? null : KTypeConverter.convert(value, type);
	}

	/**
	 * 设置值
	 * @param key 键
	 * @param value 值
	 * @return 本对象
	 */
	@ReturnNotNull
	public MainArgs putList(@CanNull final String key, @CanNull final List<String> value) {
		this.map.put(key, "[" + KListUtils.join(value, ",", null) + "]");
		return this;
	}

	/**
	 * 取值
	 * @param <T> 泛型
	 * @param type 类型
	 * @param key 键
	 * @return 值
	 */
	@ReturnNull("未配置该参数")
	@ReturnNull("配置的值为null")
	public <T> List<T> getList(@CanNotNull final Class<T> type, @CanNull final String key) {
		final String value = this.map.get(key);
		if (value == null) { return null; }
		final String[] arr = value.substring(1, value.length() - 1).split(",");
		final List<T> list = new ArrayList<>(arr.length);
		for (final String str : arr) {
			list.add(KTypeConverter.convert(str, type));
		}
		return list;
	}

	/**
	 * 设置值
	 * @param key 键
	 * @param value 值
	 * @return 本对象
	 */
	@ReturnNotNull
	public MainArgs putListMap(@CanNull final String key, @CanNull final List<Map<String, String>> value) {
		if (value != null) {
			final StringBuilder sb = new StringBuilder("[");
			value.forEach(m -> {
				sb.append("{");
				m.forEach((k, v) -> {
					sb.append("\"").append(k).append("\"").append(":").append("\"").append(v).append("\"").append(",");
				});
				sb.deleteCharAt(sb.length() - 1);
				sb.append("}").append(",");
			});
			sb.deleteCharAt(sb.length() - 1);
			this.map.put(key, sb.append("]").toString());
		} else {
			this.map.put(key, null);
		}
		return this;
	}

	/**
	 * 取值
	 * @param key 键
	 * @return 值
	 */
	@ReturnNull("未配置该参数")
	@ReturnNull("配置的值为null")
	public List<Map<String, String>> getListMap(@CanNull final String key) {
		final String value = this.map.get(key);
		if (value == null) { return null; }
		final List<Map<String, String>> list = new ArrayList<>();
		final String surplus = value.substring(1, value.length() - 1);
		this.extract(surplus).forEach(item -> {
			final Map<String, String> m = new HashMap<>();
			KMatcherUtils.extract(item, "\\\"" + "[0-9a-zA-Z]+" + "\\\"[\\s]*\\:[\\s]*\\\"" + "[^\\,]+" + "\\\"").forEach(kv -> {
				final String[] kvs = kv.split(":");
				final String k = kvs[0].trim();
				final String v = kvs[1].trim();
				m.put(k.substring(1, k.length() - 1), v.substring(1, v.length() - 1));
			});
			list.add(m);
		});
		return list;
	}

	private List<String> extract(final String str) {
		final List<String> list = new ArrayList<>();
		final char[] charArray = str.toCharArray();
		StringBuilder sb = new StringBuilder();
		int x = 0;
		for (int i = 0; i < charArray.length; i++) {
			final char c = charArray[i];
			sb.append(c);
			switch (c) {
				case '{':
					x++;
					break;
				case '}':
					x--;
					if (x == 0) {
						list.add(sb.toString());
						sb = new StringBuilder();
					}
					break;
				case ',':
					if (sb.length() == 1) { sb.deleteCharAt(0); }
					break;
				case ' ':
					if (sb.length() == 1) { sb.deleteCharAt(0); }
					break;
				default :
					break;
			}
		}
		return list;
	}

	/**
	 * 转主函数参数
	 * @return 字符串数组
	 */
	public String[] value() {
		final List<String> list = new ArrayList<>();
		this.map.forEach((key, value) -> {
			list.add(key + "=" + value);
		});
		return KListUtils.toStringArray(list);
	}

}
